require "prefabutil"

local tent_assets = {
	Asset("ANIM", "anim/musha_tent.zip"),
	Asset("ANIM", "anim/musha_tent_on.zip"),
	Asset("ANIM", "anim/musha_tent_broken.zip")
}

local function ShowFuel(inst)
	inst.components.talker:Say(math.ceil(inst.components.fueled:GetPercent() * 100) .. "%")
end

local function OnDestoryed(inst, worker)
	if inst.components.burnable ~= nil and inst.components.burnable:IsBurning() then
		inst.components.burnable:Extinguish()
	end
	inst.components.lootdropper:DropLoot()
	local fx = SpawnPrefab("collapse_big")
	fx.Transform:SetPosition(inst.Transform:GetWorldPosition())
	fx:SetMaterial("wood")
	inst:Remove()
end

local function OnHammered(inst, worker)
	if not inst:HasTag("burnt") then
		inst.AnimState:PlayAnimation("hit")
		inst.AnimState:PushAnimation("idle", true)
	end
	if inst.components.sleepingbag ~= nil and inst.components.sleepingbag.sleeper ~= nil then
		inst.components.sleepingbag:DoWakeUp()
	end
end

local function OnBroken(inst, sleeper)
	if not inst:HasTag("burnt") then
		inst.components.machine:TurnOff()
		inst.AnimState:SetBuild("musha_tent_broken")
		inst:RemoveComponent("sleepingbag")
		inst.SoundEmitter:PlaySound("dontstarve/common/tent_dis_pre")
		inst:DoTaskInTime(
			16 * FRAMES,
			function()
				inst.SoundEmitter:PlaySound("dontstarve/common/tent_dis_twirl")
			end
		)
		scheduler:ExecuteInTime(
			2,
			function()
				SpawnPrefab("collapse_big").Transform:SetPosition(inst:GetPosition():Get())
				inst.AnimState:PlayAnimation("destroy", true)
				--inst.AnimState:PlayAnimation("place")
			end
		)
	end
end

local function OnBuilt(inst)
	inst.AnimState:PlayAnimation("place")
	inst.AnimState:PushAnimation("idle", true)
end

local function OnOpen(inst, data)
	if not inst.components.fueled:IsEmpty() then
		inst.Light:Enable(true)
		inst.AnimState:SetBuild("musha_tent_on")
		inst.SoundEmitter:PlaySound("dontstarve/common/minerhatAddFuel")
		inst.components.fueled:StartConsuming()
	end
end

-----------
local function OnClose(inst, data)
	if not inst.components.fueled:IsEmpty() and not inst.using_on then
		inst.SoundEmitter:PlaySound("dontstarve/common/minerhatOut")
		inst.Light:Enable(false)
		inst.AnimState:SetBuild("musha_tent")
		inst.SoundEmitter:PlaySound("dontstarve/common/minerhatOut")
		inst.components.fueled:StopConsuming()
	end
end
-------- --------

local function OnWake(inst, sleeper, nostatechange)
	inst.sleep_anim2:Cancel()
	inst.sleep_anim2 = nil
	if sleeper:HasTag("_musha") then
		sleeper:PushEvent("onwakeup")
		sleeper.with_tent = false
	end

	inst.AnimState:SetBuild("musha_tent_on")
	if inst.components.fueled:IsEmpty() then
		inst.components.machine:TurnOff()
		inst.AnimState:SetBuild("musha_tent")
	end

	if inst.sleeptask ~= nil then
		inst.sleeptask:Cancel()
		inst.sleeptask = nil
	end

	if not nostatechange then
		if sleeper.sg:HasStateTag("tent") then
			sleeper.sg.statemem.iswaking = true
		end
		sleeper.sg:GoToState("wakeup")
	end

	if inst.sleep_anim ~= nil then
		inst.AnimState:PushAnimation("idle", true)
	end
end

local function OnSleepTick(inst, sleeper)
	if sleeper.components.sanity ~= nil and sleeper.components.sanity:GetPercentWithPenalty() < 1 then
		sleeper.components.sanity:DoDelta(TUNING.SLEEP_SANITY_PER_TICK, true)
	end

	if sleeper.components.health ~= nil then
		sleeper.components.health:DoDelta(TUNING.SLEEP_HEALTH_PER_TICK * 2, true, inst.prefab, true)
	end

	if sleeper.components.temperature ~= nil then
		if sleeper.components.temperature:GetCurrent() > TUNING.SLEEP_TARGET_TEMP_TENT then
			sleeper.components.temperature:SetTemperature(
				sleeper.components.temperature:GetCurrent() - TUNING.SLEEP_TEMP_PER_TICK
			)
		elseif sleeper.components.temperature:GetCurrent() < TUNING.SLEEP_TARGET_TEMP_TENT then
			sleeper.components.temperature:SetTemperature(
				sleeper.components.temperature:GetCurrent() + TUNING.SLEEP_TEMP_PER_TICK
			)
		end
	end

	if sleeper.components.hunger ~= nil then
		sleeper.components.hunger:DoDelta(inst.hunger_tick, true, true)
		if sleeper.components.hunger:IsStarving() then
			inst.components.sleepingbag:DoWakeUp()
		end
	end
end

local function OnSleep(inst, sleeper)
	inst.sleep_anim2 =
		inst:DoPeriodicTask(
		6,
		function()
			SpawnPrefab("green_leaves").Transform:SetPosition(inst:GetPosition():Get())
		end
	)
	if not inst.components.fueled:IsEmpty() then
		if sleeper:HasTag("_musha") then
			sleeper:PushEvent("gotosleep")
			sleeper.with_tent = true
		end

		--inst.AnimState:SetBuild("musha_tent_on")
		inst.SoundEmitter:PlaySound("dontstarve/common/minerhatAddFuel")
		if inst.sleep_anim ~= nil then
			inst.AnimState:PlayAnimation(inst.sleep_anim, true)
		end

		if inst.sleeptask ~= nil then
			inst.sleeptask:Cancel()
		end
		inst.sleeptask = inst:DoPeriodicTask(TUNING.SLEEP_TICK_PERIOD, OnSleepTick, nil, sleeper)

		inst.components.fueled.rate = 0.2
	end
end

local function TakeItem(inst, item, data)
	SpawnPrefab("small_puff").Transform:SetPosition(inst:GetPosition():Get())
	SpawnPrefab("green_leaves").Transform:SetPosition(inst:GetPosition():Get())
	--SpawnPrefab("splash").Transform:SetPosition(inst:GetPosition():Get())
	if inst.components.fueled:IsEmpty() then
		scheduler:ExecuteInTime(
			2,
			function()
				SpawnPrefab("collapse_big").Transform:SetPosition(inst:GetPosition():Get())
				inst:AddComponent("sleepingbag")
				inst.components.sleepingbag.onsleep = OnSleep
				inst.components.sleepingbag.onwake = OnWake
				inst.AnimState:PlayAnimation("place")
				inst.AnimState:PushAnimation("idle", true)
			end
		)
	end
	inst.components.fueled:DoDelta(20)
end

local function OnSave(inst, data)
	data.duration = inst.duration
	if inst:HasTag("burnt") or (inst.components.burnable ~= nil and inst.components.burnable:IsBurning()) then
		data.burnt = true
	end
end

local function OnLoad(inst, data)
	if data and data.is_On then
		inst.is_On = data.is_On
		if not inst.components.fueled:IsEmpty() then
			inst.components.machine:TurnOn()
		end
	end
	if data ~= nil and data.burnt then
		inst.components.burnable.onburnt(inst)
	end
end

local function fn()
	local inst = CreateEntity()
	inst.entity:AddTransform()
	inst.entity:AddAnimState()
	inst.entity:AddSoundEmitter()
	inst.entity:AddMiniMapEntity()
	inst.entity:AddNetwork()

	MakeObstaclePhysics(inst, 1)

	inst:AddTag("tent")
	inst:AddTag("structure")

	inst.AnimState:SetBank("tent")
	inst.AnimState:SetBuild("musha_tent")
	inst.AnimState:PlayAnimation("idle", true)
	inst.MiniMapEntity:SetIcon("musha_tent.tex")

	MakeSnowCoveredPristine(inst)

	inst.entity:AddLight()
	inst.Light:SetRadius(5)
	inst.Light:SetFalloff(.8)
	inst.Light:SetIntensity(.8)
	inst.Light:SetColour(180 / 255, 180 / 255, 180 / 255)
	inst.Light:Enable(false)

	inst:AddComponent("machine")
	inst.components.machine.turnonfn = OnOpen
	inst.components.machine.turnofffn = OnClose
	inst.components.machine.cooldowntime = 0

	inst:AddComponent("talker")
	inst.components.talker.fontsize = 21
	inst.components.talker.font = TALKINGFONT
	inst.components.talker.colour = Vector3(0.7, 0.85, 1, 1)
	inst.components.talker.offset = Vector3(0, -780, 0)
	inst.components.talker.symbol = "swap_object"

	inst:AddComponent("fueled")
	inst.components.fueled.fueltype = "BURNABLE"
	inst.components.fueled:InitializeFuelLevel(100)
	inst.components.fueled.rate = 0.004
	inst.components.fueled.bonusmult = 0
	inst.components.fueled:SetDepletedFn(OnBroken)
	inst.components.fueled:SetTakeFuelFn(TakeItem)
	inst.components.fueled.accepting = true
	inst.components.fueled:StopConsuming()

	inst.entity:SetPristine()

	if not TheWorld.ismastersim then
		return inst
	end

	inst:AddComponent("inspectable")

	inst:AddComponent("lootdropper")
	inst:AddComponent("workable")
	inst.components.workable:SetWorkAction(ACTIONS.HAMMER)
	inst.components.workable:SetWorkLeft(4)
	inst.components.workable:SetOnFinishCallback(OnDestoryed)
	inst.components.workable:SetOnWorkCallback(OnHammered)

	inst:AddComponent("sleepingbag")
	inst.components.sleepingbag.onsleep = OnSleep
	inst.components.sleepingbag.onwake = OnWake

	--convert wetness delta to drying rate
	inst.components.sleepingbag.dryingrate = math.max(0, -TUNING.SLEEP_WETNESS_PER_TICK / TUNING.SLEEP_TICK_PERIOD)

	MakeSnowCovered(inst)
	inst:ListenForEvent("onbuilt", OnBuilt)
	inst:ListenForEvent(
		"onignite",
		function(inst)
			if inst.components.sleepingbag.sleeper then
				inst.components.sleepingbag:DoWakeUp()
			end
		end
	)

	MakeLargeBurnable(inst, nil, nil, true)
	MakeMediumPropagator(inst)

	--inst:AddComponent("playerprox")
	--inst.components.playerprox:SetDist(4, 4)
	--inst.components.playerprox:SetOnPlayerNear(on_close)
	--inst.components.playerprox:SetOnPlayerFar(far)

	inst.sleep_anim = "sleep_loop"
	inst.hunger_tick = TUNING.SLEEP_HUNGER_PER_TICK
	inst:ListenForEvent("onfueldsectionchanged", ShowFuel)

	inst.OnSave = OnSave
	inst.OnLoad = OnLoad

	MakeHauntableWork(inst)

	return inst
end

return Prefab("musha_tent", fn, tent_assets), MakePlacer("musha_tent_placer", "tent", "musha_tent", "idle")
